package hu.bme.aut.consulttime.server.auth;

import jBCrypt.BCrypt;
import hu.bme.aut.consulttime.server.entities.Student;
import hu.bme.aut.consulttime.server.entities.Tutor;
import hu.bme.aut.consulttime.server.entities.User;
import hu.bme.aut.consulttime.server.entityservices.EntityManagerFactoryWrapper;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;

import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

public class CustomAuthenticationProvider implements AuthenticationProvider {

	public static final EntityManager entityManager() {
		return EntityManagerFactoryWrapper.get().createEntityManager();
	}
	
	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		
		String userName = (String)authentication.getPrincipal();
		String password = (String)authentication.getCredentials();
		
		EntityManager em = entityManager();
		User user = null;

		try {
			TypedQuery<User> query = em.createQuery(
					"select user from User user where user.userName = ?1",
					User.class);
			query.setParameter(1, userName);
			user = query.getSingleResult();
		
		} catch (Throwable t){
			throw new BadCredentialsException("Invalid username or password");
		}
		
		finally {
			if (em != null) {
				em.close();
			}
		}
		
		if (user == null) {
			throw new BadCredentialsException("Invalid username or password");
			//throw new UsernameNotFoundException("User not found");
		}
		
		if (user.getPassword().equals(password) || BCrypt.checkpw(password, user.getPassword()) == true) {
			
			String role = null;
			
			if (user.getClass() == Student.class) {
				role = "ROLE_STUDENT";
			}
			else if (user.getClass() == Tutor.class) {
				role = "ROLE_TUTOR";
			}
			
			Authentication customAuthentication = new CustomUserAuthentication(role, authentication);
			customAuthentication.setAuthenticated(true);
			
			return customAuthentication;
			
		} else {
			throw new BadCredentialsException("Invalid username or password");
		}

		
		
	}

	@Override
	public boolean supports(Class<? extends Object> authentication) {
		return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
	}

}
